import wx
from Constant import *
from PublicMethod import *
'''
GameObj_GreenWater :
    
    Game object of green water. When it turns on, this object will wait some time, then stretch to
    
    some area around the green water. If no space to stretch to, the all area of green water will
    
    turn to game object - Diamond.
'''
class GameObj_GreenWater():
    '''
    Constructor : GameObj_GreenWater
        mainMap - object pointer - MainMap
        WaitingTimeRange - the range of waiting time of stretching (minimum time-sec, maximum time-sec)
        maxOneTimeGenerate - the maximum stretching number of green water at one time
    '''
    def __init__(self, mainMap, WaitingTimeRange, maxOneTimeGenerate):
        self._001_initialInstanceVariable(mainMap, WaitingTimeRange, maxOneTimeGenerate)
        self._002_bindAction()
        self.SLOT005_playSound(None)
    '''
    function _001 : initialize the variables used for this object
        mainMap - object pointer - MainMap
        WaitingTimeRange - the range of waiting time of stretching (minimum time-sec, maximum time-sec)
        maxOneTimeGenerate - the maximum stretching number of green water at one time
    '''
    def _001_initialInstanceVariable(self, mainMap, WaitingTimeRange, maxOneTimeGenerate):
        #object pointer - MainMap
        self.mainMap = mainMap
        #current green water image index
        self.curImageIndex = 0
        #the range of waiting time of stretching (sec)
        self.WaitingTimeRange = WaitingTimeRange
        #record the maximum stretching number of green water at one time
        self.maxOneTimeGenerate = maxOneTimeGenerate
        #record all location of green water
        self.listGreenWater = []
        #record all location of area that green water can stretch to
        self.listCanStretchedArea = []
        #timer of stretch
        self.timer_stretch = wx.Timer()
        #timer of change image of green water
        self.timer_changeImage = wx.Timer()
        #timer of judge no stretching area
        self.timer_judgeNoStretchArea = wx.Timer()
        #timer of playing sound
        self.timer_playSound = wx.Timer()
    '''
    function _002 : bind object event to specific method
    '''
    def _002_bindAction(self):
        self.timer_changeImage.Bind(wx.EVT_TIMER, self.SLOT002_changeImage)
        self.timer_judgeNoStretchArea.Bind(wx.EVT_TIMER, self.SLOT003_judgeNoStretchArea)
        self.timer_stretch.Bind(wx.EVT_TIMER, self.SLOT001_randomlyStretch)
        self.timer_playSound.Bind(wx.EVT_TIMER, self.SLOT005_playSound)
        self.mainMap.evtCollector.Bind(EVT_DESTROY_GAME_OBJ, self.SLOT004_deleteGreenWater)
    '''
    function ACT001 : adding a new position of green water
    '''
    def ACT001_addNewGreenWaterArea(self, addPos):
        if self.timer_changeImage.IsRunning() :
            self.mainMap.ACT003_changeObj(addPos, GAME_OBJ_GREEN_WATER, self.curImageIndex)
        self.listGreenWater.append(addPos)
    '''
    function ACT002 : delete a green water from list - listGreenWater according to the passing position
    '''
    def ACT002_deleteGreenWaterArea(self, delPos):
        index = 0
        isDel = False
        while (not isDel) and (index < self.listGreenWater.__len__()) :
            if (self.listGreenWater[index][0] == delPos[0]) and (self.listGreenWater[index][1] == delPos[1]) :
                self.listGreenWater.__delitem__(index)
                isDel = True
            index = index + 1
    '''
    function ACT003 : set all area position that green water can stretch to
    '''
    def ACT003_setCurCanStretchArea(self):
        #delete list of stretch area
        del self.listCanStretchedArea
        self.listCanStretchedArea = []
        #add list of stretch area
        dir = [[0,1], [0,-1], [1,0], [-1,0]]
        indexGA = 0
        while indexGA < self.listGreenWater.__len__() :
            curRow = self.listGreenWater[indexGA][0]
            curCol = self.listGreenWater[indexGA][1]
            indexDir = 0
            while indexDir < dir.__len__() :
                newPos = (curRow + dir[indexDir][0], curCol + dir[indexDir][1])
                isAdd = (not self.mainMap.ACT004_judgePosIsOutOfRange(newPos)) and \
                (not LIST_IS_OBSTACLE[str(GAME_OBJ_GREEN_WATER)][self.mainMap.GET001_objTypeIn_listCube(newPos)]) and \
                (not self.listCanStretchedArea.__contains__(newPos))
                if isAdd :
                    self.listCanStretchedArea.append(newPos)
                indexDir = indexDir + 1
            indexGA = indexGA + 1
    '''
    function ACT004 : turn all green water to diamond and destroy this object
    '''
    def ACT004_turnAllToDiamond(self):
        index = 0
        while index < self.listGreenWater.__len__() :
            self.mainMap.ACT003_changeObj(self.listGreenWater[index], GAME_OBJ_DIAMOND, 0)
            self.mainMap.ACT006_createGameObj(GAME_OBJ_DIAMOND, self.listGreenWater[index])
            index = index + 1
        self.ACT005_destroy()
    '''
    function ACT005 : destroy all object of this class
    '''
    def ACT005_destroy(self):
        self.timer_changeImage.Stop()
        self.timer_changeImage.Destroy()
        self.timer_judgeNoStretchArea.Stop()
        self.timer_judgeNoStretchArea.Destroy()
        self.timer_stretch.Stop()
        self.timer_stretch.Destroy()
        self.timer_playSound.Stop()
        self.timer_playSound.Destroy()
        del self.listCanStretchedArea
        self.listCanStretchedArea = []
        del self.listGreenWater
        self.listGreenWater = []
        del self
    '''
    function ACT006 : turn on all timer of this class
    '''
    def ACT006_startTimer(self):
        self.timer_changeImage.Start(1000)
        self.timer_stretch.Start(PublicMethod.ACT003_getRandomNum(self.WaitingTimeRange[0], self.WaitingTimeRange[1]) * 1000)
        self.timer_judgeNoStretchArea.Start(1000)
        self.timer_playSound.Start(2500)
    '''
    function SLOT001 : randomly select some area in list-listCanStretchedArea and set those to be 
                       green water
    '''
    def SLOT001_randomlyStretch(self, event):
        self.ACT003_setCurCanStretchArea()
        if self.listCanStretchedArea.__len__() > 0 :  #randomly stretch to some area
            #get random stretching number of area
            max = self.maxOneTimeGenerate
            if self.listCanStretchedArea.__len__() < max :
                max = self.listCanStretchedArea.__len__()
            stretchNum = PublicMethod.ACT003_getRandomNum(1, max)
            #get stretching area list
            listStretch = PublicMethod.ACT002_getRandomDataInNum(self.listCanStretchedArea, stretchNum)
            #add stretching area to list
            index = 0
            while index < listStretch.__len__() :
                if (not LIST_IS_OBSTACLE[str(GAME_OBJ_GREEN_WATER)][self.mainMap.GET001_objTypeIn_listCube(listStretch[index])]) :
                    self.ACT001_addNewGreenWaterArea(listStretch[index])
                index = index + 1
            #set next stretching
            self.timer_stretch.Stop()
            self.timer_stretch.Start(PublicMethod.ACT003_getRandomNum(self.WaitingTimeRange[0], self.WaitingTimeRange[1]) * 1000)
        else :  #no area to stretch to
            self.ACT004_turnAllToDiamond()
    '''
    function SLOT002 : slot of changing the object image
    '''
    def SLOT002_changeImage(self, event):
        self.curImageIndex = (self.curImageIndex + 1) % LIST_FILENAME_GAMEOBJECT[GAME_OBJ_GREEN_WATER].__len__()
        index = 0
        while index < self.listGreenWater.__len__() :
            self.mainMap.ACT003_changeObj(self.listGreenWater[index], GAME_OBJ_GREEN_WATER, self.curImageIndex)
            index = index + 1
    '''
    function SLOT003 : slot of judging whether no space that green water can stretch to now
    '''
    def SLOT003_judgeNoStretchArea(self, event):
        self.ACT003_setCurCanStretchArea()
        if self.listCanStretchedArea.__len__() == 0 :
            self.ACT004_turnAllToDiamond()
    '''
    function SLOT004 : slot of delete some area of green water
    '''
    def SLOT004_deleteGreenWater(self, event):
        if not event.isClearAll :
            delObjType = event.delObjType
            delPos = event.delPos
            if delObjType == GAME_OBJ_GREEN_WATER :
                self.ACT002_deleteGreenWaterArea(delPos)
        else :
            self.ACT005_destroy()
        event.Skip()
    '''
    function SLOT005 : slot of playing sound effect
    '''
    def SLOT005_playSound(self, event):
        self.mainMap.ACT017_playSoundEffext(SOUND_WATER)